package ui.systems;

/**
 * Translates movement of pieces on the board.
 * 
 * @author Team Titanium
 */
public class BoardMoveControl {

	private static int[][] board;

	private static int player1Captures;

	private static int player2Captures;
	
	private static boolean gameOver;

	// Represent who's turn it is.
	public static final int HUMAN_PLAYER = 1, COMPUTER_PLAYER = 2;
	
	/*
	 * These represent the cardinal movements that pieces can make.
	 * The "north" side of the board is the top row and the "south" side
	 * is the bottom row.  East and west are right and left, respectively.
	 */
	public static final int MOVED_NW = 0xffff,
	MOVED_NE = 0x0fff,
	MOVED_SE = 0x00ff,
	MOVED_SW = 0x000f;
	
	/*
	 * These represent values for the squares on the board.
	 */
	public static final int EMPTY = 0, // The square is empty with no piece.
	RED = 1, // Has a red normal piece.
	RED_KING = 2, // Has a red king piece.
	BLACK = 3, // Has a black piece.
	BLACK_KING = 4; // Has a black king piece.

	// All positions not on the board are considered null.

	/**
	 * Constructor method creates "board", which will be a two dimentional
	 * array. The constructor will also create 12 pieces for each player. Then
	 * it populates the "board" by calling the setUpGame method which assigns
	 * squares based on position.
	 */
	public BoardMoveControl() {
		board = new int[8][8];
		setUpGame();

		player1Captures = 0;
		player2Captures = 0;

	}
	
	/**
	 * Initializes the board.
	 */
	public static void init() {
		board = new int[8][8];
		setUpGame();

		player1Captures = 0;
		player2Captures = 0;
	}
	
	/**
	 * Resets the board.
	 */
	public static void reset() {
		init();
	}
	
	/**
	 * Sets up the game by placing all the pieces in
	 * the starting locations.
	 */
	private static void setUpGame() {
		gameOver = false;
		for (int row = 0; row < 8; row++) {
			for (int col = 0; col < 8; col++) {
				if (row % 2 == col % 2) {
					if (row < 3)
						board[row][col] = BLACK;
					else if (row > 4)
						board[row][col] = RED;
					else
						board[row][col] = EMPTY;
				} else {
					board[row][col] = EMPTY;
				}
			}
		}
	} // end
	
	/**
	 * Get the current board.
	 * @return
	 *   An 8-by-8 array of integers.
	 */
	public static int[][] getBoard() {
		return board;
	}
	
	/**
	 * Given a MoveAction object, this method performs the move.
	 * @param move
	 *   A MoveAction object.
	 */
	public static boolean movePiece(MoveAction move) {
		return movePiece(move.data.fromRow, move.data.fromCol, move.data.toRow, move.data.toCol); 
		// Takes the data from the move object and
		// makes the specified moves.

	}
	/**
	 * Return whatever piece (or empty space) is at 
	 * the position given by <code>row, col</code>.
	 * @param row
	 *   The row.
	 * @param col
	 *   The column.
	 * @return
	 *   0 if empty; non-zero otherwise.  The non-zero 
	 *   value will indicate what player the piece belongs
	 *   to.
	 */
	public static int pieceAt(int row, int col){
		return board[row][col];
	}
	
	/**
	 * 
	 * @param oldrow
	 * @param oldcol
	 * @param newrow
	 * @param newcol
	 * @return
	 */
	private static int getMovePattern(int oldrow, int oldcol, int newrow, int newcol) {
		int ret_move_val = 0;
		
		if (newrow%2 != newcol%2) {
			return ret_move_val;
		}
		
		if (oldrow < newrow && oldcol < newcol) {
			// SE movement.
			ret_move_val = MOVED_SE;
		}
		else if (oldrow > newrow && oldcol < newcol) {
			// NE movement.
			ret_move_val = MOVED_NE;
		}
		else if (oldrow > newrow && oldcol > newcol) {
			// NW movement.
			ret_move_val = MOVED_NW;
		}
		else if (oldrow < newrow && oldcol > newcol){
			// SW movement.
			ret_move_val = MOVED_SW;
		}
		
		return ret_move_val;
	}
	
	/**
	 * Determine if a move is valid.  Regular pieces can move 
	 * either NE or NW (for red player), or SE or SW (for black player).
	 * King pieces can move either direction.
	 * @param piece
	 * 		Can be one of the constants: RED, RED_KING, BLACK, or BLACK_KING.
	 * @param mv
	 * 		Move data.
	 * @return
	 * 		TRUE if valid; FALSE otherwise.
	 */
	public static boolean isValidMove(int piece, MoveActionData mv, boolean aJump) {
		return isValidMove(piece, mv.fromRow, mv.fromCol, mv.toRow, mv.toCol, aJump);
	}
	
	private static boolean isValidMove(int piece, int fromRow, int fromCol, int toRow, int toCol, boolean aJump) {
		int delta = getMovePattern(fromRow, fromCol, toRow, toCol);
		
		// stop playing if game over
		if (gameOver) {
			return false;
		}
		
		// dont want to jump over own team
		if (aJump && getPieceJumped(fromCol, fromRow, delta) == piece) {
			return false;
		}
		
		// don't want to land on top of other pieces.
		if (pieceAt(toRow, toCol) != 0) {
			return false;
		}
		// dont want to move to own square.
		if (fromRow-toRow == 0 || fromCol-toCol == 0) {
			return false;
		}
		
		if (delta != 0 && (piece == RED_KING || piece == BLACK_KING)) {
			return true;
		}
		else if (piece == RED && (delta == MOVED_NE || delta == MOVED_NW)) {
			return true;
		}
		else if (piece == BLACK && (delta == MOVED_SE || delta == MOVED_SW)) {
			return true;
		}
		
		return false;
	}
	
	private static int getPieceJumped(int fromCol, int fromRow, int move) {
		int ret_piece = 0;
		
		switch (move) {
			case MOVED_NW:
				ret_piece = board[(fromRow-1)][(fromCol-1)];
				break;
			case MOVED_NE:
				ret_piece = board[(fromRow-1)][(fromCol+1)];
				break;
			case MOVED_SE:
				ret_piece = board[(fromRow+1)][(fromCol+1)];
				break;
			case MOVED_SW:
				ret_piece = board[(fromRow+1)][(fromCol-1)];
				break;
		}
		
		return ret_piece;
	}
	
	public static boolean isJump(int fromRow, int toRow) {
        // Method tells if the move is a jump by checking if the distance moved is equal to 2 squares.
        // The negative distance is for the opposite player.
        return (fromRow-toRow == 2 || fromRow-toRow == -2);
        
	}


	/**
	 * Method actually makes the move on the board. Method will check if the
	 * move is a jump and remove the jumped piece as well. Method will also
	 * check if the moved piece should be turned into a king.
	 */
	private static boolean movePiece(int fromRow, int fromCol, int toRow, int toCol) {
		int color_moving = board[fromRow][fromCol];
		boolean jumping = isJump(fromRow, toRow);
		
		if (!isValidMove(color_moving, fromRow, fromCol, toRow, toCol, jumping)) {
			if (gameOver) {
				System.err.println("You can't make moves!  Game is over!");
			}
			else {
				System.err.println("Illegal board move.");
			}
			return false;
		}
		
		//System.out.printf("FR: %d FC: %d :: TR: %d TC: %d\n", fromRow, fromCol, toRow, toCol);
		
		board[toRow][toCol] = board[fromRow][fromCol];
		board[fromRow][fromCol] = EMPTY; // Clear old space

		//if (isJump(fromRow, toRow) && board[(fromRow+piece_jumped)][(fromCol+piece_jumped)] != color_moving) // If move is a jump...
		if (jumping)
		{
			int toRow1 = (toRow + fromRow) / 2;
			int toCol1 = (toCol + fromCol) / 2;

			if (board[toRow][toCol] == RED || board[toRow][toCol] == RED_KING) {
				player1Captures++; // Adds a point to the capturing players counter.
			}
			if (board[toRow][toCol] == BLACK || board[toRow][toCol] == BLACK_KING) {
				player2Captures++; // Same thing for opposite player...
			}
			board[toRow1][toCol1] = EMPTY; // Delete jumped piece.
			
			System.out.printf("1c: %d 2c: %d\n", player1Captures, player2Captures);

		}
		//else if (board[(fromRow+piece_jumped)][(fromCol+piece_jumped)] == color_moving) {
			// undo our changes if the jump is not valid
		//	board[fromRow][fromCol] = color_moving;
		//	board[toRow][toCol] = EMPTY;
		//	return false;
		//}
		if (toRow == 0 && board[toRow][toCol] == RED) { // Turns piece into red
			// king if at right row.
			board[toRow][toCol] = RED_KING;
		}
		if (toRow == 7 && board[toRow][toCol] == BLACK) { // Same thing except
			// black piece.
			board[toRow][toCol] = BLACK_KING;
		}
		
		if (player1Captures == 12 || player2Captures == 12) {
			gameOver = true;
		}
		
		return true;

	}
	
	public static boolean isGameOver() {
		return gameOver;
	}

}
